using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace Crux.Core.Websockets;

/// <summary>
/// WebSocketHandleMiddlewareOfT
/// </summary>
public class WebSocketHandleMiddleware<THandler>(
    RequestDelegate next,
    ConnectionHandler connectionHandler,
    IOptions<WebSocketOptions<THandler>> options)
    where THandler : WebSocketHandler
{
    #region private fields

    /// <summary>
    ///
    /// </summary>
    private readonly RequestDelegate _next = next ?? throw new ArgumentNullException(nameof(next));

    /// <summary>
    ///
    /// </summary>
    private readonly IOptions<WebSocketOptions<THandler>> _options = options ?? throw new ArgumentNullException(nameof(options));

    /// <summary>
    ///
    /// </summary>
    private readonly ConnectionHandler _handler = connectionHandler ?? throw new ArgumentNullException(nameof(connectionHandler));
    #endregion private fields

    #region handle http request

    /// <summary>
    /// 如果不是websocket 立即执行下一步
    /// </summary>
    /// <param name="context">http上下文</param>
    /// <returns></returns>
    public async Task Invoke(HttpContext context)
    {
        if (!context.WebSockets.IsWebSocketRequest)
        {
            await _next.Invoke(context);
            return;
        }

        using var webSocket = await context.WebSockets.AcceptWebSocketAsync().ConfigureAwait(false);

        using var webSocketConnectionContext = WebSocketConnectionContext.Create(context, webSocket, _options.Value.Options);

        await _handler.OnConnectedAsync(webSocketConnectionContext).ConfigureAwait(false);
    }

    #endregion
}